#ifndef Pozisyon_h__
#define Pozisyon_h__

#include <vector>
#include <map>

#include "Exceptions.h"

#define M_PI 3.141593

/** 
 * \class Koordinat
 * \ingroup Iletisim
 * \brief Koordinat sinifi. Uzayda bir referens noktasina gore konumunu belirtir.
 * \author Mehmet Yigitsoy
 * \date $Date: 2012/12/31 11:14:00 $
 */
class Koordinat 
{
public:
	/**
	 * \brief Default constructor (disabled)
	 **/
	Koordinat(); // Bu constructorin cagrilmamasi icin sadece decl. yapip impl. yapmamak yeterli oluyor. C++11 ozelligi olan Koordinat() = delete; bu VS versiyonunda yok.
	
	/**
	 * \brief Constructor
	 * \param _x x koordinati
	 * \param _y y koordinati
	 * \param _z z koordinati
	 **/
	Koordinat(double _x, double _y, double _z) 
		: x(_x), y(_y), z(_z){}

	/**
	 * \brief Default destructor
	 **/
	~Koordinat(){}

	/**
	 * \brief Bu nesnenin butun elemanlari {@code diger} nesneden kopyalanir.
	 * \param diger
	 * \returns const Koordinat&
	 **/
	const Koordinat& operator=(const Koordinat& diger)
	{
		x = diger.x;
		y = diger.y;
		z = diger.z;

		return *this;
	}

	double x;
	double y;
	double z;
};

/** 
 * \class Oryantasyon
 * \ingroup Iletisim
 * \brief Oryantasyon sinifi. Uzayda bir referens noktasina gore oryantasyonu belirtir.
 * \author Mehmet Yigitsoy
 * \date $Date: 2012/12/31 11:14:00 $
 */
class  Oryantasyon
{
public:
	/**
	 * \brief Default constructor
	 **/
	Oryantasyon();

	/**
	 * \brief Constructor
	 * \param _alpha
	 * \param _beta
	 * \param _theta
	 **/
	Oryantasyon(double _azimuth, double _pitch, double _roll) 
		: azimuth(_azimuth), pitch(_pitch), roll(_roll){}
	
	/**
	 * \brief Default destructor
	 * \returns 
	 **/
	~Oryantasyon(){}

	/**
	 * \brief Esitleme islemi
	 * \param diger Esitlenecek nesne
	 * \returns const Oryantasyon& Simdiki nesneye referans
	 **/
	const Oryantasyon& operator=(const Oryantasyon& diger)
	{
		if (aciDegeriDogruMu(azimuth))
			azimuth = diger.azimuth;
		else
			throw new MuyatException("Aci standard araligin disinda!");
		
		if (aciDegeriDogruMu(pitch))
			pitch = diger.pitch;
		else
			throw new MuyatException("Aci standard araligin disinda!");

		if (aciDegeriDogruMu(roll))
			roll = diger.roll;
		else
			throw new MuyatException("Aci standard araligin disinda!");

		return *this;
	}

	/**
	 * \brief Aci test methodu
	 * \param aci Test edilecek aci
	 * \returns aci degeri {@code 0} ve {@code 2pi} arasindaysa {@code true},
	 * degilse {@code false}
	 **/
	bool aciDegeriDogruMu(double aci){ return aci>=0 && aci <= 2*M_PI; }

	double azimuth;
	double pitch;
	double roll;	
};

/** 
 * \class Pozisyon
 * \ingroup Iletisim
 * \brief Pozisyon sinifi. Uzayda bir referens noktasina gore pozisyonu (koordinate+oryantasyon) belirtir.
 * \author Mehmet Yigitsoy
 * \date $Date: 2012/12/31 11:14:00 $
 */
class Pozisyon 
{
public:
	
	/**
	 * \brief Default constructor
	 **/
	Pozisyon();


	/**
	 * \brief 
	 * \param x
	 * \param y
	 * \param z
	 * \param azimuth
	 * \param pitch
	 * \param roll
	 * \returns 
	 **/
	Pozisyon(double x, double y, double z, double azimuth, double pitch, double roll) 
	{
		this->koordinat = new Koordinat(x,y,z);
		this->oryantasyon = new Oryantasyon(azimuth, pitch, roll);
	}

	/**
	 * \brief Constructor
	 * \param _koordinat Koordinat bilgisi
	 * \param _oryantasyon Oryanstasyon bilgisi
	 **/
	Pozisyon(const Koordinat _koordinat, const Oryantasyon _oryantasyon)
	{

		this->koordinat = new Koordinat(_koordinat);
		this->oryantasyon = new Oryantasyon(_oryantasyon);
	}

	/**
	 * \brief Default destructor
	 **/
	~Pozisyon()
	{
		if(koordinat)	delete koordinat;
		if(oryantasyon) delete oryantasyon;
	};

	/**
	 * \brief Esitleme islemi
	 * \param diger Esitlenecek diger nesne
	 * \returns const Pozisyon& Simdiki nesneye referans
	 **/
	const Pozisyon& operator=(const Pozisyon& diger)
	{
		*(this->koordinat) = *(diger.koordinat);
		*(this->oryantasyon) = *(diger.oryantasyon);

		return *this;
	};

	Koordinat *koordinat;
	Oryantasyon*oryantasyon;

};

typedef int							YorungeId;
typedef std::vector<Pozisyon*>		Yorunge;
typedef std::map<YorungeId,Yorunge>	YorungeList;

#endif // Pozisyon_h__